package io.gitee.chearnee.fw.web.advice;

import cn.hutool.extra.spring.SpringUtil;
import io.gitee.chearnee.fw.common.model.vo.ResultVo;
import io.gitee.chearnee.fw.web.exception.ApiException;
import io.gitee.chearnee.fw.web.exception.InternalServiceApiException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.HashSet;
import java.util.Set;

/**
 * @author NN
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandlerAdvice {
    private static final Set<String> devProfiles;

    static {
        devProfiles = new HashSet<>();
        devProfiles.add("dev");
        devProfiles.add("test");
    }
    @ExceptionHandler(value = ApiException.class)
    public ResultVo<Void> handle(ApiException e) {
        return ResultVo.fail(e.getResultCode(), e.getMessage());
    }

    @ExceptionHandler(value = InternalServiceApiException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultVo<Void> serviceHandle(InternalServiceApiException e) {
        return ResultVo.fail(e.getMessage());
    }

    @ExceptionHandler(ConstraintViolationException.class)
    public ResultVo<Void> exceptionHandler(
            ConstraintViolationException e) {
        // 然后提取错误提示信息进行返回
        return ResultVo.fail(e.getMessage());
    }

    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResultVo<Void> exceptionHandler(MethodArgumentTypeMismatchException e, HttpServletRequest serverHttpRequest) {
        String uri = "";
        if (serverHttpRequest != null) {
            uri = serverHttpRequest.getRequestURI();
        }
        log.warn("业务异常:MethodArgumentTypeMismatchException:uri:{}", uri, e);
        return ResultVo.fail("请传入正确的参数");
    }
    @ExceptionHandler(IllegalArgumentException.class)
    public ResultVo<Void> exceptionHandler(IllegalArgumentException e) {
        log.info("业务异常:IllegalArgumentException", e);
        return ResultVo.fail(e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultVo<Void> methodArgumentNotValidExceptionHandler(
            MethodArgumentNotValidException e) {
        // 从异常对象中拿到ObjectError对象
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        // 然后提取错误提示信息进行返回
        return ResultVo.fail(objectError.getDefaultMessage());
    }

    @ExceptionHandler(BindException.class)
    public ResultVo<Void> bindExceptionHandler(BindException e) {
        // 从异常对象中拿到ObjectError对象
        ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
        // 然后提取错误提示信息进行返回
        return ResultVo.fail(objectError.getDefaultMessage());
    }

    @ExceptionHandler(NoHandlerFoundException.class)
    public ResultVo<Void> noHandlerFoundExceptionHandler(NoHandlerFoundException e) {
        // 然后提取错误提示信息进行返回
        return ResultVo.fail(e.getMessage());
    }

    @ExceptionHandler(RuntimeException.class)
    public ResultVo<Void> exceptionHandler(RuntimeException e, HttpServletRequest serverHttpRequest) {
        String uri = "";
        if (serverHttpRequest != null) {
            uri = serverHttpRequest.getRequestURI();
        }
        log.error("业务异常uri:{}:RuntimeException", uri, e);
        String msg = e.getMessage();
        if (!devProfiles.contains(SpringUtil.getActiveProfile())) {
            msg = "服务内部错误,请联系管理员";
        }
        return ResultVo.fail(msg);
    }

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResultVo<Void> exceptionHandler(HttpMessageNotReadableException e, HttpServletRequest serverHttpRequest) {
        String uri = "";
        if (serverHttpRequest != null) {
            uri = serverHttpRequest.getRequestURI();
        }
        log.warn("业务异常:HttpMessageNotReadableException:uri:{}", uri, e);
        return ResultVo.fail("请传入正确的参数");
    }

    @ExceptionHandler(ServletRequestBindingException.class)
    public ResultVo<Void> exceptionHandler(ServletRequestBindingException e, HttpServletRequest serverHttpRequest) {
        String uri = "";
        if (serverHttpRequest != null) {
            uri = serverHttpRequest.getRequestURI();
        }
        log.warn("业务异常:ServletRequestBindingException:uri:{}", uri, e);
        return ResultVo.fail("请传入正确的参数");
    }
}
